package com.wxzz.elearing.pay.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.wxzz.elearing.pay.entity.PayLog;
import com.wxzz.elearing.pay.entity.UserOrder;
import com.wxzz.elearing.pay.entity.UserTransaction;
import com.wxzz.elearing.pay.entity.UserWallet;
import com.wxzz.elearing.pay.mapper.PayLogMapper;
import com.wxzz.elearing.pay.mapper.UserOrderMapper;
import com.wxzz.elearing.pay.mapper.UserTransactionMapper;
import com.wxzz.elearing.pay.service.IUserTransactionService;
import com.wxzz.elearing.pay.service.IUserWalletService;
import com.wxzz.elearing.pay.service.IWxPayService;
import com.wxzz.elearing.pay.service.openfeign.*;
import com.wxzz.elearing.pay.wx.mini.WxToPay;
import com.wxzz.elearning.common.constants.OrderConstants;
import com.wxzz.elearning.common.dto.FeignUserWalletDto;
import com.wxzz.elearning.common.utils.OpenFeignUtil;
import com.wxzz.elearning.common.vo.ReturnVO;
import io.seata.spring.annotation.GlobalTransactional;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;

/**
 * 小程序端微信支付
 */
@Service
public class WxPayServiceImpl implements IWxPayService {

    private final static Logger logger = LoggerFactory.getLogger(WxPayServiceImpl.class);

    @Autowired
    private IWxUserApiFeign wxUserApiFeign;

    @Resource
    private UserOrderMapper userOrderMapper;

    @Autowired
    private UserTransactionMapper userTransactionMapper;

    @Autowired
    private PayLogMapper payLogMapper;


    //========================================小程序端微信支付=======================================================

    /**
     * wxUserId 微信用户id
     * ipaddress ip地址
     * serialid 订单编号
     * payMoney 支付金额
     * userType 用户类型
     * orderTitle 订单标题
     * modelType 模块类型
     *
     * @param map
     * @return
     */
    @Transactional
    @Override
    public Map orderPay(Map<String, String> map) {
        //调用用户模块
        ReturnVO<String> stringReturnVO = wxUserApiFeign.selectWxUserByWxUserId(Long.valueOf(map.get("wxUserId")));
        JSONObject jsonObject = OpenFeignUtil.getJSONObject(stringReturnVO);
        String returnJson = WxToPay.payMsg(map.get("ipaddress"), jsonObject.getString("openid"), map.get("serialid"), map.get("payMoney"));
        //=======================生成订单=================================
        UserOrder userOrder = new UserOrder();
        userOrder.setUserId(Long.valueOf(map.get("wxUserId")));
        userOrder.setUserType(Integer.valueOf(map.get("userType")));
        userOrder.setPayName(jsonObject.getString("nickname"));
        userOrder.setPhone(jsonObject.getString("phone"));
        userOrder.setIncomePrice(new BigDecimal(map.get("payMoney")));
        if (StringUtils.isNotBlank(map.get("businessId"))) {
            userOrder.setBusinessId(Long.valueOf(map.get("businessId")));
        }
        userOrder.setOrderNum(map.get("serialid"));
        userOrder.setOrderTitle(map.get("orderTitle"));
        userOrder.setPayType(OrderConstants.PAY_TYPE_WX);
        userOrder.setModelType(Integer.valueOf(map.get("modelType")));
        userOrderMapper.insert(userOrder);
        Map<String, String> returnMap = new HashMap<>();
        returnMap.put("returnJson", returnJson);
        returnMap.put("orderId", userOrder.getId().toString());
        //==================支付日志================================
        PayLog payLog = new PayLog();
        payLog.setPayInfo(String.valueOf(map));
        payLog.setOrderNum(map.get("serialid"));
        payLogMapper.insert(payLog);
        return returnMap;
    }

    @Autowired
    private IWxCourseApiFeign wxCourseApiFeign;

    @Autowired
    private IWxLivetelecastApiFeign wxLivetelecastApiFeign;

    @Autowired
    private ICurriculumApiFeign curriculumApiFeign;

    @Autowired
    private IWxPayApiFeign iWxPayApi;

    @Autowired
    private IUserWalletService userWalletService;

    @Autowired
    private IUserTransactionService userTransactionService;

    @GlobalTransactional
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void handlerNotify(HttpServletRequest request, HttpServletResponse response) throws IOException {
        String paySerialid = WxToPay.getPaySerialid(request, payLogMapper);
        //验签并获得支付回调商户订单号
        UserOrder userOrder = userOrderMapper.selectOne(new LambdaQueryWrapper<UserOrder>()
                .eq(UserOrder::getOrderNum, paySerialid));
        if (userOrder == null) {
            logger.error("订单编号[{}]的订单不存在", paySerialid);
            return;
        }
        //修改订单状态为已支付
        userOrder.setPayTime(LocalDateTime.now());
        userOrder.setOrderStatus(1);
        userOrderMapper.updateById(userOrder);

        UserTransaction userTransaction = new UserTransaction();
        userTransaction.setMoney(userOrder.getIncomePrice());
        //课程模块
        if (OrderConstants.MODEL_TYPE_CURRICULUM.equals(userOrder.getModelType())) {
            //修改订单支付状态
            ReturnVO<String> stringReturnVO = wxCourseApiFeign.handlerNotifyCurriculum(userOrder.getId());
            if (!"200".equals(stringReturnVO.getCode())) {
                logger.error("课程模块支付状态修改失败,对应订单id[{}],返回对象[{}]", userOrder.getId(), stringReturnVO.toString());
                return;
            } else {
                //查询课程对应的企业或平台
                ReturnVO<JSONObject> jsonObjectReturnVO = curriculumApiFeign.selectCurriculumByOrderId(userOrder.getId());
                if (!"200".equals(jsonObjectReturnVO.getCode())) {
                    logger.error("课程模块支付查询课程信息失败,对应订单id[{}],返回对象[{}]", userOrder.getId(), jsonObjectReturnVO.toString());
                    return;
                }
                JSONObject data = jsonObjectReturnVO.getData();
                //平台课程的收益
                // if (data.getInteger("curriculumType")==0){
                if (data.getInteger("curriculumType") == 0) {
                    //更新钱包余额
                    UserWallet userWallet = userWalletService.updateUserWallet(data.getLong("enterpriseId"), 0, userOrder.getIncomePrice());
                    userTransaction.setBalance(userWallet.getUserBalance());
                    userTransaction.setDescription("用户购买平台课程");
                    userTransaction.setBusinessRemark("订单编号:" + userOrder.getOrderNum());
                    userTransaction.setUserType(0);
                    userTransaction.setUsername(userTransactionService.getUserName(0, data.getLong("enterpriseId")));
                }
                //企业课程的收益
                //if (data.getInteger("curriculumType")==1){
                if (data.getLong("enterpriseId") != 0) {
                    //更新钱包余额
                    UserWallet userWallet = userWalletService.updateUserWallet(data.getLong("enterpriseId"), 1, userOrder.getIncomePrice());
                    userTransaction.setBalance(userWallet.getUserBalance());
                    userTransaction.setDescription("用户购买企业课程");
                    userTransaction.setBusinessRemark("订单编号:" + userOrder.getOrderNum());
                    userTransaction.setUserType(1);
                    userTransaction.setUsername(userTransactionService.getUserName(1, data.getLong("enterpriseId")));
                }
                //计入流水
                userTransaction.setType(0);
                userTransaction.setUserId(data.getLong("enterpriseId"));
                userTransaction.setTransactionStatus("存入余额");
                userTransaction.setChangeType("用户购买课程");
                userTransactionMapper.insert(userTransaction);
            }
        }
        //直播和平台暂时都是平台的收益
        //直播模块
        if (OrderConstants.MODEL_TYPE_LIVE.equals(userOrder.getModelType())) {
            ReturnVO<String> stringReturnVO = wxLivetelecastApiFeign.handlerNotifyLive(userOrder.getId());
            if (!"200".equals(stringReturnVO.getCode())) {
                logger.error("直播模块支付状态修改失败,对应订单id[{}],返回对象[{}]", userOrder.getId(), stringReturnVO.toString());
                return;
            } else {
                //更新钱包余额
                UserWallet userWallet = userWalletService.updateUserWallet(0L, 0, userOrder.getIncomePrice());
                userTransaction.setBalance(userWallet.getUserBalance());
                userTransaction.setDescription("用户购买直播");
                userTransaction.setBusinessRemark("订单编号:" + userOrder.getOrderNum());
                userTransaction.setUserType(0);
                userTransaction.setType(0);
                userTransaction.setUserId(0L);
                userTransaction.setUsername(userTransactionService.getUserName(0, 0L));
                userTransaction.setTransactionStatus("存入余额");
                userTransaction.setChangeType("用户购买直播");
                userTransactionMapper.insert(userTransaction);
            }
        }
        //活动模块
        if (OrderConstants.MODEL_TYPE_ACTIVITY.equals(userOrder.getModelType()) || OrderConstants.MODEL_TYPE_ACTIVITY_OFF.equals(userOrder.getModelType())) {
            ReturnVO<String> stringReturnVO = wxLivetelecastApiFeign.handlerNotifyLive(userOrder.getId());
            if (!"200".equals(stringReturnVO.getCode())) {
                logger.error("活动模块支付状态修改失败,对应订单id[{}],返回对象[{}]", userOrder.getId(), stringReturnVO.toString());
                return;
            } else {
                //更新钱包余额
                UserWallet userWallet = userWalletService.updateUserWallet(0L, 0, userOrder.getIncomePrice());
                userTransaction.setBalance(userWallet.getUserBalance());
                userTransaction.setDescription("用户购买活动");
                userTransaction.setBusinessRemark("订单编号:" + userOrder.getOrderNum());
                userTransaction.setUserType(0);
                userTransaction.setType(0);
                userTransaction.setUserId(0L);
                userTransaction.setUsername(userTransactionService.getUserName(0, 0L));
                userTransaction.setTransactionStatus("存入余额");
                userTransaction.setChangeType("用户购买活动");
                userTransactionMapper.insert(userTransaction);
            }
        }
        //问答模块
        if (OrderConstants.MODEL_TYPE_QUESTIONS_ANSWERS.equals(userOrder.getModelType())) {
            ReturnVO<String> stringReturnVO = iWxPayApi.iQuestionsAnswersListService(userOrder.getId());
            if (!"200".equals(stringReturnVO.getCode())) {
                logger.error("问答模块支付状态修改失败,对应订单id[{}],返回对象[{}]", userOrder.getId(), stringReturnVO.toString());
                return;
            } else {
                //更新钱包余额
                UserWallet userWallet = userWalletService.updateUserWallet(0L, 0, userOrder.getIncomePrice());
                userTransaction.setBalance(userWallet.getUserBalance());
                userTransaction.setDescription("用户赏金暂存");
                userTransaction.setBusinessRemark("订单编号:" + userOrder.getOrderNum());
                userTransaction.setUserType(0);
                userTransaction.setType(0);
                userTransaction.setUserId(0L);
                userTransaction.setUsername(userTransactionService.getUserName(0, 0L));
                userTransaction.setTransactionStatus("存入余额");
                userTransaction.setChangeType("用户赏金暂存");
                userTransactionMapper.insert(userTransaction);
            }
        }
        //直播打赏
        if (OrderConstants.MODEL_TYPE_LIVE_REWARD.equals(userOrder.getModelType())) {
            Map<String, String> map = new HashMap<>();
            map.put("businessId", userOrder.getBusinessId().toString());
            map.put("rewardAmount", userOrder.getIncomePrice().toString());
            ReturnVO<Long> longReturnVO = wxLivetelecastApiFeign.updateRewardAmount(map);
            if (!"200".equals(longReturnVO.getCode())) {
                logger.error("直播打赏模块支付状态修改失败,对应订单id[{}],返回对象[{}]", userOrder.getId(), longReturnVO.toString());
                return;
            } else {
                //更新钱包余额
                UserWallet userWallet = userWalletService.updateUserWallet(longReturnVO.getData(), 3, userOrder.getIncomePrice());
                userTransaction.setBalance(userWallet.getUserBalance());
                userTransaction.setDescription("用户打赏直播");
                userTransaction.setBusinessRemark("订单编号:" + userOrder.getOrderNum());
                userTransaction.setUserType(3);
                userTransaction.setType(0);
                userTransaction.setUserId(longReturnVO.getData());
                userTransaction.setUsername(userTransactionService.getUserName(3, longReturnVO.getData()));
                userTransaction.setTransactionStatus("存入余额");
                userTransaction.setChangeType("用户打赏直播");
                userTransactionMapper.insert(userTransaction);
            }
        }
        //==================支付日志================================
        PayLog payLog = payLogMapper.selectOne(new LambdaQueryWrapper<PayLog>()
                .eq(PayLog::getOrderNum, paySerialid));
        payLog.setLogType(1);
        payLogMapper.updateById(payLog);
        //告诉微信不用重复通知
        String xml = "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/xml; charset=utf-8");
        PrintWriter out = response.getWriter();
        out.print(xml);
        out.close();
    }
}
